package com.engine.salary.entity.taxagent.bo;

import com.engine.salary.constant.SalaryDefaultTenantConstant;
import com.engine.salary.entity.agency.po.PaymentAgencyPO;
import com.engine.salary.entity.auth.po.AuthRolePO;
import com.engine.salary.entity.datacollection.DataCollectionEmployee;
import com.engine.salary.entity.hrm.DeptInfo;
import com.engine.salary.entity.hrm.HrmStatus;
import com.engine.salary.entity.hrm.PositionInfo;
import com.engine.salary.entity.hrm.SubCompanyInfo;
import com.engine.salary.entity.taxagent.dto.TaxAgentEmployeeDTO;
import com.engine.salary.entity.taxagent.dto.TaxAgentListDTO;
import com.engine.salary.entity.taxagent.dto.TaxAgentManageRangeListDTO;
import com.engine.salary.entity.taxagent.dto.TaxAgentSubAdminListDTO;
import com.engine.salary.entity.taxagent.param.TaxAgentManageRangeSaveParam;
import com.engine.salary.entity.taxagent.param.TaxAgentSaveParam;
import com.engine.salary.entity.taxagent.param.TaxAgentSubAdminRangeSaveParam;
import com.engine.salary.entity.taxagent.po.TaxAgentAdminPO;
import com.engine.salary.entity.taxagent.po.TaxAgentManageRangePO;
import com.engine.salary.entity.taxagent.po.TaxAgentPO;
import com.engine.salary.entity.taxagent.po.TaxAgentSubAdminPO;
import com.engine.salary.enums.salarysob.TargetTypeEnum;
import com.engine.salary.enums.taxagent.TaxAgentRangeTypeEnum;
import com.engine.salary.util.JsonUtil;
import com.engine.salary.util.SalaryEntityUtil;
import com.engine.salary.util.SalaryI18nUtil;
import com.engine.salary.util.page.Column;
import com.engine.salary.util.page.PageInfo;
import com.google.common.base.Joiner;
import com.google.common.collect.Lists;
import com.engine.salary.util.db.IdGenerator;
import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Data;
import lombok.NoArgsConstructor;
import org.apache.commons.collections4.CollectionUtils;
import org.apache.commons.lang3.StringUtils;

import java.util.*;
import java.util.stream.Collectors;

/**
 * 个税扣缴义务人
 * <p>Copyright: Copyright (c) 2022</p>
 * <p>Company: 泛微软件</p>
 *
 * @author qiantao
 * @version 1.0
 **/
public class TaxAgentBO {

    @Override
    public String toString() {
        return "TaxAgentBO{}";
    }

    /**
     * 根据个税扣缴义务人id和用户id判断是否匹配
     *
     * @param taxAgentEmployees
     * @param taxAgentId
     * @param employeeId
     * @return
     */
    public static boolean checkTaxAgentAndEmployee(List<TaxAgentEmployeeDTO> taxAgentEmployees, Long taxAgentId, Long employeeId) {
        if (CollectionUtils.isEmpty(taxAgentEmployees) && taxAgentId == null) {
            return false;
        }
        return taxAgentEmployees.stream().anyMatch(t -> t.getTaxAgentId().equals(taxAgentId) && employeeId.equals(t.getEmployeeId()));
    }

    /**
     * 构建表格
     *
     * @param isOpenDevolution
     */
    public static void buildTaxAgentTable(PageInfo<Map<String, Object>> listPage, boolean isOpenDevolution) {
        // 表格表头
        List<Column> columns = new ArrayList<>();
        String name = SalaryI18nUtil.getI18nLabel(91558, "个税扣缴义务人名称");
        String employeeRange = SalaryI18nUtil.getI18nLabel(86125, "人员范围");
        String admins = SalaryI18nUtil.getI18nLabel(106259, "管理员");
        String subAdmins = SalaryI18nUtil.getI18nLabel(106283, "分管理员");
//        String paymentAgency = SalaryI18nUtil.getI18nLabel(112448, "社保福利代缴机构");
        String description = SalaryI18nUtil.getI18nLabel(84961, "备注");
        String sortedIndex = SalaryI18nUtil.getI18nLabel(84962, "显示顺序");

        columns.add(new Column(name, "name", "name"));
        columns.add(new Column(employeeRange, "employeeRange", "employeeRange"));
        if (isOpenDevolution) {
            columns.add(new Column(admins, "admins", "admins"));
        }
        columns.add(new Column(description, "description", "description"));
        columns.add(new Column(sortedIndex, "sortedIndex", "sortedIndex"));
        listPage.setColumns(columns);
    }

    /**
     * 表数据转列表数据
     *
     * @param taxAgents
     * @return
     */
    public static List<TaxAgentListDTO> convertToListDTO(Collection<TaxAgentPO> taxAgents) {
        if (CollectionUtils.isEmpty(taxAgents)) {
            return Collections.emptyList();
        }
        return taxAgents.stream()
                .map(e -> TaxAgentListDTO.builder()
                        .id(e.getId())
                        .name(e.getName())
                        .description(e.getDescription())
                        .build())
                .collect(Collectors.toList());
    }

    /**
     * 表数据转列表数据
     *
     * @param taxAgents
     * @return
     */
    public static List<Map<String, Object>> convertToTableListDTO(List<TaxAgentPO> taxAgents, List<PaymentAgencyPO> paymentAgencyPOS) {
        return convertToTableListDTO(Boolean.FALSE, taxAgents, paymentAgencyPOS, null, null);
    }

    /**
     * 表数据转列表数据
     *
     * @param taxAgents
     * @return
     */
    public static List<Map<String, Object>> convertToTableListDTO(List<TaxAgentPO> taxAgents, List<PaymentAgencyPO> paymentAgencyPOS, List<TaxAgentAdminPO> taxAgentAdmins,
                                                                  List<DataCollectionEmployee> adminList) {
        return convertToTableListDTO(Boolean.TRUE, taxAgents, paymentAgencyPOS, taxAgentAdmins, adminList);
    }

    /**
     * 表数据转列表数据
     *
     * @param taxAgents
     * @param adminList
     * @return
     */
    public static List<Map<String, Object>> convertToTableListDTO(Boolean isDevolution, List<TaxAgentPO> taxAgents, List<PaymentAgencyPO> paymentAgencyPOS,
                                                                  List<TaxAgentAdminPO> taxAgentAdmins,
                                                                  List<DataCollectionEmployee> adminList) {
        if (CollectionUtils.isEmpty(taxAgents)) {
            return Collections.emptyList();
        }
        return taxAgents.stream()
                .map(e -> {
                    Map<String, Object> map = new LinkedHashMap<>();
                    map.put("id", e.getId());
                    map.put("name", e.getName());
                    map.put("employeeRange", "设置");
//                    map.put("role", rolelistMap.getOrDefault(e.getId(), Collections.emptyList()).stream().map(AuthRolePO::getName).collect(Collectors.joining(",")));
                    if (isDevolution) {
                        List<Long> empIds = taxAgentAdmins.stream().filter(t -> t.getTaxAgentId().equals(e.getId())).map(TaxAgentAdminPO::getEmployeeId).collect(Collectors.toList());
                        List<String> admins = adminList.stream().filter(a -> empIds.contains(a.getEmployeeId())).map(DataCollectionEmployee::getUsername).collect(Collectors.toList());
                        map.put("admins", CollectionUtils.isEmpty(admins) ? "" : Joiner.on(",").join((Iterable<?>) admins));
                        map.put("subAdmins", "设置");
                    }
                    map.put("paymentAgency", buildPaymentAgency(e.getPaymentAgency(), paymentAgencyPOS));
                    map.put("description", e.getDescription());
                    map.put("sortedIndex", e.getSortedIndex());
                    return map;
                }).collect(Collectors.toList());
    }

    public static List<Map<String, Object>> buildPaymentAgency(String originStr, List<PaymentAgencyPO> paymentAgencyPOS) {
        List<Map<String, Object>> paymentAgencyList = new ArrayList<>();
        if (CollectionUtils.isEmpty(paymentAgencyPOS)) {
            return paymentAgencyList;
        }
        originStr = StringUtils.isBlank(originStr) ? "" : originStr;
        String finalOriginStr = originStr;
        return paymentAgencyPOS.stream().map(e -> {
            HashMap<String, Object> temp = new HashMap<>();
            temp.put("id", e.getId());
            temp.put("agencyName", e.getAgencyName());
            if (finalOriginStr.contains(String.valueOf(e.getId()))) {
                temp.put("status", true);
            } else {
                temp.put("status", false);
            }
            return temp;
        }).collect(Collectors.toList());
    }

    /**
     * 保存参数转表数据
     *
     * @param saveParam
     * @param employeeId
     * @return
     */
    public static TaxAgentPO convertToPO(TaxAgentSaveParam saveParam, Long employeeId) {
        if (saveParam == null) {
            return null;
        }
        Date now = new Date();
        return TaxAgentPO.builder()
//                .id(saveParam.getId())
                .name(saveParam.getName())
                .description(saveParam.getDescription())
                .createTime(now)
                .updateTime(now)
                .creator(employeeId)
                .deleteType(0)
                .tenantKey(SalaryDefaultTenantConstant.DEFAULT_TENANT_KEY)
                .sortedIndex(saveParam.getSortedIndex())
                .build();
    }

    /**
     * 表数据转列表数据（分管理员）
     *
     * @param list
     * @param range
     * @param subAdminList
     * @return
     */
    public static List<TaxAgentSubAdminListDTO> convertToSubAdminListDTO(List<TaxAgentSubAdminPO> list, String range, List<DataCollectionEmployee> subAdminList) {
        if (CollectionUtils.isEmpty(list)) {
            return Collections.emptyList();
        }
        return list.stream()
                .map(e -> {
                    Optional<String> optionalUsername = subAdminList.stream().filter(a -> e.getEmployeeId().equals(a.getEmployeeId())).map(DataCollectionEmployee::getUsername).findFirst();
                    return TaxAgentSubAdminListDTO.builder()
                            .id(e.getId())
                            .subAdmin(optionalUsername.isPresent() ? optionalUsername.get() : "")
                            .range(range)
                            .description(e.getRemark())
                            .build();
                })
                .collect(Collectors.toList());
    }

    /**
     * 管理范围列表转换
     *
     * @param taxAgentManageRanges
     * @param employeeComInfos
     * @param departmentComInfos
     * @param subDepartmentComInfos
     * @param positionComInfos
     * @param hrmStatusList
     * @return
     */
    public static List<TaxAgentManageRangeListDTO> convert2ListDTO(List<TaxAgentManageRangePO> taxAgentManageRanges, List<DataCollectionEmployee> employeeComInfos,
                                                                   List<DeptInfo> departmentComInfos, List<SubCompanyInfo> subDepartmentComInfos,
                                                                   List<PositionInfo> positionComInfos, List<HrmStatus> hrmStatusList) {
        if (CollectionUtils.isEmpty(taxAgentManageRanges)) {
            return Collections.emptyList();
        }
        Map<Long, String> employeeComInfoMap = SalaryEntityUtil.convert2Map(employeeComInfos, DataCollectionEmployee::getEmployeeId, DataCollectionEmployee::getUsername);
        Map<Long, String> departmentComInfoMap = SalaryEntityUtil.convert2Map(departmentComInfos, DeptInfo::getId, DeptInfo::getName);
        Map<Long, String> subDepartmentComInfoMap = SalaryEntityUtil.convert2Map(subDepartmentComInfos, SubCompanyInfo::getId, SubCompanyInfo::getName);
        Map<Long, String> positionComInfoMap = SalaryEntityUtil.convert2Map(positionComInfos, PositionInfo::getId, PositionInfo::getName);

        Map<String, String> hrmStatusNameMap = SalaryEntityUtil.convert2Map(hrmStatusList, hrmStatus -> String.valueOf(hrmStatus.getId()), HrmStatus::getName);

        return taxAgentManageRanges.stream()
                .map(taxAgentManageRange -> {
                    TargetTypeEnum targetTypeEnum = TargetTypeEnum.parseByValue(taxAgentManageRange.getTargetType());
                    return TaxAgentManageRangeListDTO.builder()
                            .id(taxAgentManageRange.getId())
                            .targetType(targetTypeEnum)
                            .targetTypeName(Optional.ofNullable(targetTypeEnum)
                                    .map(e -> SalaryI18nUtil.getI18nLabel(e.getLabelId(), e.getDefaultLabel()))
                                    .orElse(StringUtils.EMPTY))
                            .targetId(taxAgentManageRange.getTargetId())
                            .target(taxAgentManageRange.getTarget())
                            .targetName(buildTargetName(taxAgentManageRange, employeeComInfoMap, departmentComInfoMap, subDepartmentComInfoMap, positionComInfoMap))
                            .employeeStatus(buildEmployeeStatus(hrmStatusNameMap, taxAgentManageRange.getEmployeeStatus()))
                            .status(buildStatus(taxAgentManageRange.getEmployeeStatus()))
                            .build();
                })
                .collect(Collectors.toList());
    }

    private static String buildEmployeeStatus(Map<String, String> hrmStatusNameMap, String employeeStatus) {
        List<String> employeeStatusList = JsonUtil.parseList(employeeStatus, String.class);
        if (CollectionUtils.isEmpty(employeeStatusList)) {
            return StringUtils.EMPTY;
        }
        return employeeStatusList.stream()
                .map(hrmStatusNameMap::get)
                .collect(Collectors.joining(","));
    }

    private static String buildStatus( String employeeStatus) {
        List<String> employeeStatusList = JsonUtil.parseList(employeeStatus, String.class);
        if (CollectionUtils.isEmpty(employeeStatusList)) {
            return StringUtils.EMPTY;
        }
        return String.join(",", employeeStatusList);
    }

    /**
     * 构建对象名
     *
     * @param taxAgentManageRange
     * @param employeeComInfoMap
     * @param departmentComInfoMap
     * @param subDepartmentComInfoMap
     * @param positionComInfoMap
     * @return
     */
    private static String buildTargetName(TaxAgentManageRangePO taxAgentManageRange, Map<Long, String> employeeComInfoMap, Map<Long, String> departmentComInfoMap,
                                          Map<Long, String> subDepartmentComInfoMap, Map<Long, String> positionComInfoMap) {
        TargetTypeEnum targetTypeEnum = TargetTypeEnum.parseByValue(taxAgentManageRange.getTargetType());
        if (Objects.isNull(targetTypeEnum)) {
            return StringUtils.EMPTY;
        }
        switch (targetTypeEnum) {
            case EMPLOYEE:
                return employeeComInfoMap.getOrDefault(taxAgentManageRange.getTargetId(), StringUtils.EMPTY);
            case DEPT:
                return departmentComInfoMap.getOrDefault(taxAgentManageRange.getTargetId(), StringUtils.EMPTY);
            case SUBCOMPANY:
                return subDepartmentComInfoMap.getOrDefault(taxAgentManageRange.getTargetId(), StringUtils.EMPTY);
            case POSITION:
                return positionComInfoMap.getOrDefault(taxAgentManageRange.getTargetId(), StringUtils.EMPTY);
            case SQL:
                return taxAgentManageRange.getTarget();
            default:
                return StringUtils.EMPTY;
        }
    }

    public static Result handleTaxAgentRange(List<TaxAgentManageRangePO> taxAgentManageRanges, TaxAgentManageRangeSaveParam saveParam, Long taxAgentId, Long employeeId, boolean isImport) {
        return handleManageRange(taxAgentManageRanges, saveParam, TaxAgentRangeTypeEnum.TAXAGENT, taxAgentId, 0L, employeeId, isImport);
    }

    /**
     * 处理前端传回的保存参数，转换成对应的po（如果保存参数中的人员、部门、岗位等之前就已经添加过了，就不需要再次保存了）
     *
     * @param taxAgentManageRanges
     * @param saveParam
     * @param taxAgentId
     * @param subAdminId
     * @param employeeId
     * @return
     */
    private static Result handleManageRange(List<TaxAgentManageRangePO> taxAgentManageRanges, TaxAgentManageRangeSaveParam saveParam,
                                            TaxAgentRangeTypeEnum rangeTypeEnum, Long taxAgentId, Long subAdminId, Long employeeId, boolean isImport) {
        Date now = new Date();
        Result handleResult = Result.builder()
                .needInsertTaxAgentManageRanges(Lists.newArrayList())
                .needUpdateTaxAgentManageRanges(Lists.newArrayList())
                .build();
        if (CollectionUtils.isEmpty(saveParam.getTargetParams())) {
            return handleResult;
        }
        Map<String, TaxAgentManageRangePO> taxAgentManageRangeMap = SalaryEntityUtil.convert2Map(taxAgentManageRanges,
                e -> e.getIncludeType() + "-" + e.getTargetType() + "-" + e.getTargetId() + "-" + e.getRangeType());
        for (TaxAgentSubAdminRangeSaveParam.TaxAgentSubAdminRangeTargetParam targetParam : saveParam.getTargetParams()) {
            if (targetParam.getTargetType() == TargetTypeEnum.SQL) {
                TaxAgentManageRangePO taxAgentManageRange = TaxAgentManageRangePO.builder()
                        .id(IdGenerator.generate())
                        .taxAgentId(taxAgentId)
                        .taxAgentSubAdminId(subAdminId)
                        .rangeType(rangeTypeEnum.getValue())
                        .targetType(targetParam.getTargetType().getValue())
                        .targetId(0L)
                        .target(targetParam.getTarget())
                        .includeType(saveParam.getIncludeType())
                        .creator(employeeId)
                        .createTime(now)
                        .updateTime(now)
                        .tenantKey(SalaryDefaultTenantConstant.DEFAULT_TENANT_KEY)
                        .deleteType(0)
                        .build();
                if (isImport) {
                    taxAgentManageRange.setEmployeeStatus(JsonUtil.toJsonString(targetParam.getEmployeeStatus()));
                } else {
                    taxAgentManageRange.setEmployeeStatus(JsonUtil.toJsonString(saveParam.getEmployeeStatus()));
                }
                handleResult.getNeedInsertTaxAgentManageRanges().add(taxAgentManageRange);
            } else {
                String key = saveParam.getIncludeType() + "-" + targetParam.getTargetType().getValue() + "-" + targetParam.getTargetId() + "-" + rangeTypeEnum.getValue();
                if (taxAgentManageRangeMap.containsKey(key)) {
                    TaxAgentManageRangePO taxAgentManageRange = taxAgentManageRangeMap.get(key);
                    if (isImport) {
                        taxAgentManageRange.setEmployeeStatus(JsonUtil.toJsonString(targetParam.getEmployeeStatus()));
                    } else {
                        taxAgentManageRange.setEmployeeStatus(JsonUtil.toJsonString(saveParam.getEmployeeStatus()));
                    }
                    taxAgentManageRange.setUpdateTime(now);
                    handleResult.getNeedUpdateTaxAgentManageRanges().add(taxAgentManageRange);
                    continue;
                }
                TaxAgentManageRangePO taxAgentManageRange = TaxAgentManageRangePO.builder()
                        .id(IdGenerator.generate())
                        .taxAgentId(taxAgentId)
                        .taxAgentSubAdminId(subAdminId)
                        .rangeType(rangeTypeEnum.getValue())
                        .targetType(targetParam.getTargetType().getValue())
                        .targetId(targetParam.getTargetId())
                        .includeType(saveParam.getIncludeType())
                        .creator(employeeId)
                        .createTime(now)
                        .updateTime(now)
                        .tenantKey(SalaryDefaultTenantConstant.DEFAULT_TENANT_KEY)
                        .deleteType(0)
                        .build();
                if (isImport) {
                    taxAgentManageRange.setEmployeeStatus(JsonUtil.toJsonString(targetParam.getEmployeeStatus()));
                } else {
                    taxAgentManageRange.setEmployeeStatus(JsonUtil.toJsonString(saveParam.getEmployeeStatus()));
                }
                handleResult.getNeedInsertTaxAgentManageRanges().add(taxAgentManageRange);
            }
        }
        return handleResult;
    }

    @Data
    @Builder
    @NoArgsConstructor
    @AllArgsConstructor
    public static class Result {

        /**
         * 需要更新的人员范围
         */
        private Collection<TaxAgentManageRangePO> needUpdateTaxAgentManageRanges;

        /**
         * 需要新增的人员范围
         */
        private Collection<TaxAgentManageRangePO> needInsertTaxAgentManageRanges;
    }
}
